package dnet

import (
	"dgo/goutils/utils"
	"fmt"
	"net"
	"sync/atomic"
	"time"
)

/*
*

	只能TCP, UDP方式不一样
*/
type NetListener struct {
	startflag      int32
	listener       net.Listener
	network        string
	addr           string
	last_err       string
	isTerminated   bool
	HandleConnFunc func(conn net.Conn)
	OnErr          func(err error)
	OnListenSucc   func(network, addr string)
}

func NewNetListener() *NetListener {
	rval := &NetListener{}
	return rval
}

func (this *NetListener) innerClose() {
	if this.listener != nil {
		this.listener.Close()
		this.listener = nil
	}
}

func (this *NetListener) Active() bool {
	return this.startflag == 1
}

func (this *NetListener) Config(network, addr string) bool {
	rval := false
	if this.network != network {
		this.network = network
		rval = true
	}

	if this.addr != addr {
		this.addr = addr
		rval = true
	}
	if rval {
		this.innerClose()
	}
	return rval
}

/*
**

	1: 侦听成功

-1: 侦听失败

	0: 未启动
*/
func (this *NetListener) Status() int {
	if this.startflag == 0 {
		return 0
	}
	if this.listener != nil {
		return 1
	} else {
		return -1
	}
}

func (this *NetListener) StatusString() string {
	if this.startflag == 0 {
		return "未启动"
	}
	ls := this.listener
	if ls != nil {
		return fmt.Sprintf("[%s]侦听成功", ls.Addr().String())
	} else {
		return this.last_err
	}
}

func (this *NetListener) CheckStart() {
	if atomic.CompareAndSwapInt32(&this.startflag, 0, 1) {
		utils.GoFunc2(this.Open)
	}
}

func (this *NetListener) BreakConnect() {
	if this.listener != nil {
		this.listener.Close()
	}
}

func (this *NetListener) Close() {
	this.isTerminated = true
	this.innerClose()
	this.startflag = 0
}

func (this *NetListener) Open() {
	this.isTerminated = false
begin:
	if this.isTerminated {
		return
	}
	var listener net.Listener
	var l net.Listener
	var err error
	for {
		if len(this.addr) == 0 || len(this.network) == 0 {
			this.last_err = fmt.Sprintf("[%s]没有配置连接(network:%s, addr:%s)!", utils.NowString(), this.network, this.addr)
			if this.OnErr != nil {
				this.OnErr(fmt.Errorf("没有配置连接(network:%s, addr:%s)!", this.network, this.addr))
			}
			time.Sleep(time.Second * 30)
			continue
		}
		l, err = net.Listen(this.network, this.addr)
		if err != nil {
			this.last_err = fmt.Sprintf("[%s]侦听失败:(network:%s, addr:%s), %s", utils.NowString(), this.network, this.addr, err.Error())
			if this.OnErr != nil {
				this.OnErr(err)
			}
			time.Sleep(time.Second * 30)
			continue
		} else {
			if this.OnListenSucc != nil {
				this.OnListenSucc(this.network, this.addr)
			}
		}
		this.listener = l
		listener = l
		break
	}
	for {
		client, err := listener.Accept()
		if err != nil {
			if this.OnErr != nil {
				this.OnErr(err)
			}
			goto begin
		}

		if this.HandleConnFunc != nil {
			this.HandleConnFunc(client)
		}
	}
}
